package com.wie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wie.BaseContext.BaseContext;
import com.wie.constant.MessageConstant;
import com.wie.domain.dto.*;
import com.wie.domain.entity.Email;
import com.wie.domain.entity.User;
import com.wie.domain.vo.UserInfoVO;
import com.wie.exception.AccountAlreadyExistException;
import com.wie.exception.AccountNotFoundException;
import com.wie.exception.IncorrectVerificationCodeException;
import com.wie.exception.PasswordErrorException;
import com.wie.mapper.EmailMapper;
import com.wie.properties.EmailProperties;
import com.wie.service.UserService;
import com.wie.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author WiedersehenM
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2025-03-01 11:28:00
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmailMapper emailMapper;
    @Autowired
    private EmailProperties emailProperties;
    @Autowired
    private JavaMailSender javaMailSender;

    /**
     * 发送邮箱验证码
     *
     * @param signupDTO
     */
    @Transactional
    public void sendCode(SignupDTO signupDTO) {
        // 确认该用户不存在
        Map map = new HashMap();
        map.put("username", signupDTO.getUsername());
        List userList = userMapper.selectByMap(map);
        if (userList != null && userList.size() != 0) {
            throw new AccountAlreadyExistException(MessageConstant.ACCOUNT_ALREADY_EXISTS);
        }
        // 生成四位数邮箱验证码
        Random random = new Random();
        int verificationCode = random.nextInt(9000) + 1000;
        // 向用户的邮箱发送验证码
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject(emailProperties.getSubject());
        message.setText(Integer.toString(verificationCode));
        message.setFrom(emailProperties.getFrom());
        message.setTo(signupDTO.getEmail());
        javaMailSender.send(message);
        // 将验证码和对应的邮箱账号存入数据库内
        Email email = new Email().builder()
                .email(signupDTO.getEmail())
                .code(verificationCode)
                .createTime(LocalDateTime.now())
                .expirationTime(LocalDateTime.now().plus(5, ChronoUnit.MINUTES))
                .build();
        emailMapper.insert(email);
    }

    /**
     * 用户注册
     *
     * @param verifyDTO
     */
    @Transactional
    public void signup(VerifyDTO verifyDTO) {
        // 校验验证码
        QueryWrapper<Email> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Email::getEmail, verifyDTO.getEmail())
                .le(Email::getCreateTime, LocalDateTime.now())
                .ge(Email::getExpirationTime, LocalDateTime.now());
        Email email = emailMapper.selectOne(wrapper);
        if (!verifyDTO.getCode().equals(Integer.toString(email.getCode())) || email == null) {
            log.info("邮箱验证码错误");
            throw new IncorrectVerificationCodeException(MessageConstant.INCORRECT_VERIFICATION_CODE);
        }
        // 将用户插入数据库中
        User user = new User().builder()
                .email(verifyDTO.getEmail())
                .username(verifyDTO.getUsername())
                .password(verifyDTO.getPassword())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
        userMapper.insert(user);
    }

    /**
     * 账号密码登录
     *
     * @param loginDTO
     * @return
     */
    @Transactional
    public User login1(LoginWithPasswordDTO loginDTO) {
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        // 查找用户是否存在
        List<User> userList = lambdaQuery()
                .eq(User::getUsername, username)
                .list();
        if (userList == null || userList.size() == 0) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        User user = userList.get(0);
        if (!password.equals(user.getPassword())) {
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        return user;
    }

    /**
     * 邮箱登录
     * 发送验证码
     *
     * @param loginDTO
     */
    @Transactional
    public void login2(LoginWithEmailDTO loginDTO) {
        String username = loginDTO.getUsername();
        // 查找用户是否存在
        List<User> userList = lambdaQuery()
                .eq(User::getUsername, username)
                .list();
        if (userList.size() == 0 || userList == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        User user = userList.get(0);
        // 生成四位数邮箱验证码
        Random random = new Random();
        int verificationCode = random.nextInt(9000) + 1000;
        // 向用户的邮箱发送验证码
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject(emailProperties.getSubject());
        message.setText(Integer.toString(verificationCode));
        message.setFrom(emailProperties.getFrom());
        message.setTo(loginDTO.getEmail());
        javaMailSender.send(message);
        // 将验证码插入数据库中
        Email email = new Email().builder()
                .email(loginDTO.getEmail())
                .code(verificationCode)
                .createTime(LocalDateTime.now())
                .expirationTime(LocalDateTime.now().plus(5, ChronoUnit.MINUTES))
                .build();
        emailMapper.insert(email);
    }

    /**
     * 邮箱登录
     * 校验验证码
     *
     * @param loginDTO
     * @return
     */
    @Transactional
    public User login3(LoginWithEmailDTO loginDTO) {
        // 校验验证码
        QueryWrapper<Email> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Email::getEmail, loginDTO.getEmail())
                .le(Email::getCreateTime, LocalDateTime.now())
                .ge(Email::getExpirationTime, LocalDateTime.now());
        List<Email> emailList = emailMapper.selectList(wrapper);
        Email email = emailList.get(0);
        if (!loginDTO.getCode().equals(Integer.toString(email.getCode())) || email == null) {
            log.info("邮箱验证码错误");
            throw new IncorrectVerificationCodeException(MessageConstant.INCORRECT_VERIFICATION_CODE);
        }
        List<User> userList = lambdaQuery()
                .eq(User::getUsername, loginDTO.getUsername())
                .list();
        User user = userList.get(0);
        return user;
    }

    /**
     * 删除用户
     *
     * @param username
     */
    @Transactional
    public void delete(String username) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("username", username);
        userMapper.deleteByMap(map);
    }

    /**
     * 获取当前用户信息
     * @return
     */
    public UserInfoVO getUserInfo() {
        // 获取当前线程中的 userId
        Integer userId = BaseContext.getCurrentId();
        // 在数据库中查询用户信息
        User user = getById(userId);
        UserInfoVO userInfoVO = new UserInfoVO().builder()
                .username(user.getUsername())
                .userImg(user.getUserImg())
                .email(user.getEmail())
                .only(user.getOnly())
                .build();
        return userInfoVO;
    }

    /**
     * 更新用户信息
     * @param updateUserInfoDTO
     * @return
     */
    public void updateUserInfo(UpdateUserInfoDTO updateUserInfoDTO) {
        User user = new User();
        user.setId(BaseContext.getCurrentId());
        user.setUsername(updateUserInfoDTO.getUsername());
        user.setUserImg(updateUserInfoDTO.getUserImg());
        user.setEmail(updateUserInfoDTO.getEmail());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.updateById(user);
    }

    /**
     * 改变用户的单点登录
     */
    public void updateOnly() {
        Integer userId = BaseContext.getCurrentId();
        User user = getById(userId);
        User newUser = new User();
        newUser.setId(userId);
        newUser.setOnly(!user.getOnly());
        newUser.setUpdateTime(LocalDateTime.now());
        userMapper.updateById(user);
    }

    /**
     * 更新用户密码
     * @param updatePassDTO
     */
    public void updatePass(UpdatePassDTO updatePassDTO) {
        Integer userId = BaseContext.getCurrentId();
        // 判断旧密码是否正确
        User user = getById(userId);
        if (!updatePassDTO.getOldPassword().equals(user.getPassword())) {
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        // 更新密码
        User newUser = new User();
        newUser.setId(userId);
        newUser.setPassword(updatePassDTO.getNewPassword());
        newUser.setUpdateTime(LocalDateTime.now());
        userMapper.updateById(newUser);
    }
}




